<!--

Part of this page is based on the OpenAI Chatbot example by David Härer:
https://github.com/david-haerer/chatapi

MIT License Copyright (c) 2023 David Härer
            Copyright (c) 2024-2025 Ettore Di Giacinto

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

-->
<!doctype html>
<html lang="en">
  {{template "views/partials/head" .}}
  <script defer src="static/chat.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js"></script>
  <script>
    // Initialize PDF.js worker
    pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';
  </script>
  {{ $allGalleryConfigs:=.GalleryConfig }}
  {{ $model:=.Model}}
  <body class="bg-[#101827] text-[#E5E7EB] flex flex-col h-screen" x-data="{ sidebarOpen: true }">
    {{template "views/partials/navbar" .}}

    <!-- Main container with sidebar toggle -->
    <div class="flex flex-1 overflow-hidden relative">
      <!-- Sidebar -->
      <div
        class="sidebar bg-[#1E293B] fixed top-16 bottom-0 left-0 w-64 transform transition-transform duration-300 ease-in-out z-30 border-r border-[#101827] overflow-y-auto"
        :class="sidebarOpen ? 'translate-x-0' : '-translate-x-full'">

        <div class="p-4 flex justify-between items-center border-b border-[#101827]">
          <h2 class="text-lg font-semibold text-[#E5E7EB]">Chat Settings</h2>
          <button
            @click="sidebarOpen = false"
            class="text-[#94A3B8] hover:text-[#E5E7EB] focus:outline-none">
            <i class="fa-solid fa-times"></i>
          </button>
        </div>

        <!-- Sidebar content -->
        <div class="p-4 space-y-6">
          <!-- Model selection - Fixed to properly select current model -->
          <div class="space-y-2">
            <label class="text-sm font-medium text-[#94A3B8]">Select Model</label>
            <select
              id="modelSelector"
              class="w-full bg-[#101827] text-[#E5E7EB] border border-[#1E293B] focus:border-[#38BDF8] focus:ring-2 focus:ring-[#38BDF8]/50 rounded-md shadow-sm p-2 appearance-none"
              onchange="window.location = this.value"
            >
              <option value="" disabled class="text-[#94A3B8]">Select a model</option>

              {{ range .ModelsConfig }}
                {{ $cfg := . }}
                {{ range .KnownUsecaseStrings }}
                  {{ if eq . "FLAG_CHAT" }}
                    <option
                      value="chat/{{$cfg.Name}}"
                      {{ if eq $cfg.Name $model }} selected {{end}}
                      class="bg-[#101827] text-[#E5E7EB]"
                    >
                      {{$cfg.Name}}
                    </option>
                  {{ end }}
                {{ end }}
              {{ end }}
              {{ range .ModelsWithoutConfig }}
                <option
                  value="chat/{{.}}"
                  {{ if eq . $model }} selected {{ end }}
                  class="bg-[#101827] text-[#E5E7EB]"
                >
                  {{.}}
                </option>
              {{end}}
            </select>
          </div>

          {{ if $model }}
          {{ $galleryConfig:= index $allGalleryConfigs $model}}
          {{ if $galleryConfig }}
          <!-- Model info -->
          <div class="space-y-2">
            <div class="flex items-center">
              {{ if $galleryConfig.Icon }}<img src="{{$galleryConfig.Icon}}" class="rounded-lg w-8 h-8 mr-2">{{end}}
              <h3 class="text-md font-medium">{{ $model }}</h3>
            </div>
            <button data-twe-ripple-init data-twe-ripple-color="light" class="w-full text-left flex items-center px-3 py-2 text-xs rounded text-[#E5E7EB] bg-[#101827] hover:bg-[#101827]/80 border border-[#38BDF8]/20 transition-colors" data-modal-target="model-info-modal" data-modal-toggle="model-info-modal">
              <i class="fas fa-info-circle mr-2 text-[#38BDF8]"></i>
              Model Information
            </button>
          </div>
          {{ end }}
          {{ end }}

          <div x-data="{ activeTab: 'actions' }" class="space-y-4">
            <!-- Tab navigation -->
            <div class="flex border-b border-[#101827]">
              <button
                @click="activeTab = 'actions'"
                :class="activeTab === 'actions' ? 'border-b-2 border-[#38BDF8] text-[#E5E7EB]' : 'text-[#94A3B8] hover:text-[#E5E7EB]'"
                class="py-2 px-4 text-sm font-medium">
                Actions
              </button>
              <button
                @click="activeTab = 'settings'"
                :class="activeTab === 'settings' ? 'border-b-2 border-[#38BDF8] text-[#E5E7EB]' : 'text-[#94A3B8] hover:text-[#E5E7EB]'"
                class="py-2 px-4 text-sm font-medium">
                Settings
              </button>
            </div>

            <!-- Actions tab -->
            <div x-show="activeTab === 'actions'" class="space-y-3">
              <button
                @click="$store.chat.clear()"
                id="clear"
                title="Clear chat history"
                class="w-full flex items-center px-3 py-2 text-sm rounded text-[#E5E7EB] bg-[#101827] hover:bg-[#101827]/80 border border-[#1E293B] transition-colors"
              >
                <i class="fa-solid fa-trash-can mr-2"></i> Clear chat
              </button>

              <a
                href="https://localai.io/features/text-generation/"
                target="_blank"
                class="w-full flex items-center px-3 py-2 text-sm rounded text-white bg-gray-700 hover:bg-gray-600 transition-colors"
              >
                <i class="fas fa-book mr-2"></i> Documentation
              </a>

              <a
                href="browse?term={{.Model}}"
                class="w-full flex items-center px-3 py-2 text-sm rounded text-white bg-gray-700 hover:bg-gray-600 transition-colors"
              >
                <i class="fas fa-brain mr-2"></i> Browse Model
              </a>
            </div>

            <!-- Settings tab -->
            <div x-show="activeTab === 'settings'" x-data="{ showPromptForm: false }" class="space-y-3">
              {{ if $model }}
              {{ $galleryConfig:= index $allGalleryConfigs $model}}
              {{ if $galleryConfig }}
              {{ $modelConfig := "" }}
              {{ range .ModelsConfig }}
                {{ if eq .Name $model }}
                  {{ $modelConfig = . }}
                {{ end }}
              {{ end }}
              {{ if and $modelConfig (or (ne $modelConfig.MCP.Servers "") (ne $modelConfig.MCP.Stdio "")) }}
              <!-- MCP Toggle -->
              <div class="flex items-center justify-between px-3 py-2 text-sm rounded text-white bg-gray-700">
                <span><i class="fa-solid fa-plug mr-2"></i> Agentic MCP Mode</span>
                <label class="relative inline-flex items-center cursor-pointer">
                  <input type="checkbox" id="mcp-toggle" class="sr-only peer" x-model="$store.chat.mcpMode">
                  <div class="w-11 h-6 bg-gray-600 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-blue-600"></div>
                </label>
              </div>

              <!-- MCP Mode Notification -->
              <div x-show="$store.chat.mcpMode" class="p-3 bg-blue-900/20 border border-blue-700/50 rounded text-blue-100 text-xs">
                <div class="flex items-start space-x-2">
                  <i class="fa-solid fa-info-circle text-blue-400 mt-0.5"></i>
                  <div>
                    <p class="font-medium text-blue-200 mb-1">Non-streaming Mode Active</p>
                    <p class="text-blue-300">Responses will be processed in full before display. This may take significantly longer (up to 5 minutes), especially on CPU-only systems.</p>
                  </div>
                </div>
              </div>
              {{ end }}
              {{ end }}
              {{ end }}

              <button
                @click="showPromptForm = !showPromptForm"
                class="w-full flex items-center justify-between px-3 py-2 text-sm rounded text-white bg-gray-700 hover:bg-gray-600 transition-colors"
              >
                <span><i class="fa-solid fa-message mr-2"></i> System Prompt</span>
                <i :class="showPromptForm ? 'fa-chevron-up' : 'fa-chevron-down'" class="fa-solid"></i>
              </button>

              <div x-show="showPromptForm" x-data="{
                showToast: false,
                previousPrompt: $store.chat.systemPrompt,
                isUpdated() {
                  if (this.previousPrompt !== $store.chat.systemPrompt) {
                    this.showToast = true;
                    this.previousPrompt = $store.chat.systemPrompt;
                    setTimeout(() => {this.showToast = false;}, 2000);
                  }
                } 
              }" class="p-3 bg-gray-700 rounded">
                <form id="system_prompt" @submit.prevent="isUpdated" class="flex flex-col space-y-2">
                  <textarea
                    type="text"
                    id="systemPrompt"
                    name="systemPrompt"
                    class="bg-gray-800 text-white border border-gray-600 focus:border-blue-500 focus:ring focus:ring-blue-500 focus:ring-opacity-50 rounded-md shadow-sm p-2 appearance-none min-h-24"
                    placeholder="System prompt"
                    x-model.lazy="$store.chat.systemPrompt"
                  ></textarea>
                  <div
                    x-show="showToast"
                    x-transition
                    class="mb-2 text-green-500 px-4 py-2 text-sm text-center"
                  >
                    System prompt updated!
                  </div>
                  <button
                    type="submit"
                    class="px-3 py-2 text-sm rounded text-white bg-blue-600 hover:bg-blue-700 transition-colors"
                  >
                    Save System Prompt
                  </button>
                </form>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- Main chat container (shifts with sidebar) -->
      <div
        class="flex-1 flex flex-col transition-all duration-300 ease-in-out"
        :class="sidebarOpen ? 'ml-64' : 'ml-0'">

        <!-- Chat header with toggle button -->
        <div class="border-b border-gray-700 p-4 flex items-center">
          <!-- Sidebar toggle button moved to be the first element in the header and with clear styling -->
          <button
            @click="sidebarOpen = !sidebarOpen"
            class="mr-4 text-gray-300 hover:text-white focus:outline-none bg-gray-800 hover:bg-gray-700 p-2 rounded"
            style="min-width: 36px;"
            title="Toggle settings">
            <i class="fa-solid" :class="sidebarOpen ? 'fa-times' : 'fa-bars'"></i>
          </button>

          <div class="flex items-center">
            <i class="fa-solid fa-comments mr-2"></i>
            {{ if $model }}
            {{ $galleryConfig:= index $allGalleryConfigs $model}}
            {{ if $galleryConfig }}
            {{ if $galleryConfig.Icon }}<img src="{{$galleryConfig.Icon}}" class="rounded-lg w-8 h-8 mr-2">{{end}}
            {{ end }}
            {{ end }}
            <h1 class="text-lg font-semibold">
              Chat {{ if .Model }} with {{.Model}} {{ end }}
            </h1>
          </div>
        </div>

        <!-- Chat messages area -->
        <div class="flex-1 p-4 overflow-auto" id="chat" x-data="{history: $store.chat.history}">
          <p id="usage" x-show="history.length === 0" class="text-gray-300">
            Start chatting with the AI by typing a prompt in the input field below and pressing Enter.<br>
            <ul class="list-disc list-inside">
              <li>For models that support images, you can upload an image by clicking the <i class="fa-solid fa-image"></i> icon.</li>
              <li>For models that support audio, you can upload an audio file by clicking the <i class="fa-solid fa-microphone"></i> icon.</li>
              <li>To send a text, markdown or PDF file, click the <i class="fa-solid fa-file"></i> icon.</li>
            </ul>
          </p>
          <div id="messages" class="max-w-3xl mx-auto">
            <template x-for="message in history">
              <div :class="message.role === 'user' ? 'flex items-start space-x-2 my-2 justify-end' : 'flex items-start space-x-2 my-2'">
                {{ if .Model }}
                {{ $galleryConfig:= index $allGalleryConfigs .Model}}
                <template x-if="message.role === 'user'">
                  <div class="flex items-center space-x-2">
                    <div class="flex flex-col flex-1 items-end">
                      <span class="text-xs font-semibold text-gray-400">You</span>
                      <div class="p-2 flex-1 rounded bg-gray-700 text-white" x-html="message.html"></div>
                      <template x-if="message.image && message.image.length > 0">
                        <div class="mt-2 space-y-2">
                          <template x-for="(img, index) in message.image" :key="index">
                            <img :src="img" :alt="'Image ' + (index + 1)" class="rounded-lg max-w-xs">
                          </template>
                        </div>
                      </template>
                      <template x-if="message.audio && message.audio.length > 0">
                        <div class="mt-2 space-y-2">
                          <template x-for="(audio, index) in message.audio" :key="index">
                            <audio controls class="w-full">
                              <source :src="audio" type="audio/*">
                              Your browser does not support the audio element.
                            </audio>
                          </template>
                        </div>
                      </template>
                    </div>
                  </div>
                </template>
                <template x-if="message.role === 'thinking'">
                  <div class="flex items-center space-x-2 w-full">
                    <div class="flex flex-col flex-1">
                      <div class="p-2 flex-1 rounded bg-blue-900/50 text-blue-100 border border-blue-700/50">
                        <div class="flex items-center space-x-2">
                          <i class="fa-solid fa-brain text-blue-400"></i>
                          <span class="text-xs font-semibold text-blue-300">Thinking</span>
                        </div>
                        <div class="mt-1" x-html="message.html"></div>
                      </div>
                    </div>
                  </div>
                </template>
                <template x-if="message.role != 'user' && message.role != 'thinking'">
                  <div class="flex items-center space-x-2">
                    {{ if $galleryConfig }}
                    {{ if $galleryConfig.Icon }}<img src="{{$galleryConfig.Icon}}" class="rounded-lg mt-2 max-w-8 max-h-8">{{end}}
                    {{ end }}
                    <div class="flex flex-col flex-1">
                      <span class="text-xs font-semibold text-gray-400">{{if .Model}}{{.Model}}{{else}}Assistant{{end}}</span>
                      <div class="flex-1 text-white flex items-center space-x-2">
                        <div x-html="message.html"></div>
                        <button @click="copyToClipboard(message.html)" title="Copy to clipboard" class="text-gray-400 hover:text-gray-100">
                          <i class="fa-solid fa-copy"></i>
                        </button>
                      </div>
                      <template x-if="message.image && message.image.length > 0">
                        <div class="mt-2 space-y-2">
                          <template x-for="(img, index) in message.image" :key="index">
                            <img :src="img" :alt="'Image ' + (index + 1)" class="rounded-lg max-w-xs">
                          </template>
                        </div>
                      </template>
                      <template x-if="message.audio && message.audio.length > 0">
                        <div class="mt-2 space-y-2">
                          <template x-for="(audio, index) in message.audio" :key="index">
                            <audio controls class="w-full">
                              <source :src="audio" type="audio/*">
                              Your browser does not support the audio element.
                            </audio>
                          </template>
                        </div>
                      </template>
                    </div>
                  </div>
                </template>
                {{ else }}
                <i
                  class="fa-solid h-8 w-8"
                  :class="message.role === 'user' ? 'fa-user' : 'fa-robot'"
                ></i>
                {{ end }}
              </div>
            </template>
          </div>
        </div>


          <!-- Chat Input -->
          <div class="p-4 border-t border-gray-700" x-data="{ inputValue: '', shiftPressed: false, fileName: '', isLoading: false }">
            <form id="prompt" action="chat/{{.Model}}" method="get" @submit.prevent="submitPrompt" class="max-w-3xl mx-auto">
              <div class="relative w-full bg-gray-800 rounded-xl shadow-md">
                <textarea
                  id="input"
                  name="input"
                  x-model="inputValue"
                  placeholder="Send a message..."
                  class="p-4 pr-16 w-full bg-gray-800 text-gray-100 placeholder-gray-400 focus:outline-none resize-none border-0 rounded-xl transition-colors duration-200"
                  required
                  @keydown.shift="shiftPressed = true"
                  @keyup.shift="shiftPressed = false"
                  @keydown.enter="if (!shiftPressed) { submitPrompt($event); }"
                  rows="3"
                  style="box-shadow: 0 0 0 1px rgba(75, 85, 99, 0.4) inset;"
                ></textarea>
                <span x-text="fileName" id="fileName" class="absolute right-16 top-4 text-gray-400 text-sm mr-2"></span>
                <button
                  type="button"
                  onclick="document.getElementById('input_image').click()"
                  class="fa-solid fa-image text-gray-400 absolute right-12 top-4 text-lg p-2 hover:text-blue-400 transition-colors duration-200"
                  title="Attach images"
                ></button>
                <button
                  type="button"
                  onclick="document.getElementById('input_audio').click()"
                  class="fa-solid fa-microphone text-gray-400 absolute right-20 top-4 text-lg p-2 hover:text-blue-400 transition-colors duration-200"
                  title="Attach an audio file"
                ></button>
                <button
                  type="button"
                  onclick="document.getElementById('input_file').click()"
                  class="fa-solid fa-file text-gray-400 absolute right-28 top-4 text-lg p-2 hover:text-blue-400 transition-colors duration-200"
                  title="Upload text, markdown or PDF file"
                ></button>

                <!-- Send button and loader in the same position -->
                <div class="absolute right-3 top-4">
                  <!-- Loader (hidden by default) -->
                  <div id="loader" class="text-lg p-2" style="display: none;">
                    <svg class="animate-spin h-5 w-5 text-blue-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
                      <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
                      <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
                    </svg>
                  </div>

                  <!-- Send button -->
                  <button
                    id="send-button"
                    type="submit"
                    class="text-lg p-2 text-gray-400 hover:text-blue-400 transition-colors duration-200"
                    title="Send message"
                  >
                    <i class="fa-solid fa-paper-plane"></i>
                  </button>
                </div>
              </div>
            </form>
            <input id="chat-model" type="hidden" value="{{.Model}}">
            <input
              id="input_image"
              type="file"
              multiple
              accept="image/*"
              style="display: none;"
              @change="fileName = $event.target.files.length + ' image(s) selected'"
            />
            <input
              id="input_audio"
              type="file"
              multiple
              accept="audio/*"
              style="display: none;"
              @change="fileName = $event.target.files.length + ' audio file(s) selected'"
            />
            <input
              id="input_file"
              type="file"
              multiple
              accept=".txt,.md,.pdf"
              style="display: none;"
              @change="fileName = $event.target.files.length + ' file(s) selected'"
            />
          </div>
          </form>
        </div>
      </div>
    </div>

    <!-- Modal moved outside of sidebar to appear in center of page -->
    {{ if $model }}
    {{ $galleryConfig:= index $allGalleryConfigs $model}}
    {{ if $galleryConfig }}
    <div id="model-info-modal" tabindex="-1" aria-hidden="true" class="hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 flex justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full">
      <div class="relative p-4 w-full max-w-2xl max-h-full">
        <div class="relative p-4 w-full max-w-2xl max-h-full bg-white rounded-lg shadow dark:bg-gray-700">
          <!-- Header -->
          <div class="flex items-center justify-between p-4 md:p-5 border-b rounded-t dark:border-gray-600">
            <h3 class="text-xl font-semibold text-gray-900 dark:text-white">{{ $model }}</h3>
            <button class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white" data-modal-hide="model-info-modal">
              <svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
                <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"/>
              </svg>
              <span class="sr-only">Close modal</span>
            </button>
          </div>

          <!-- Body -->
          <div class="p-4 md:p-5 space-y-4">
            <div class="flex justify-center items-center">
              {{ if $galleryConfig.Icon }}<img class="lazy rounded-t-lg max-h-48 max-w-96 object-cover mt-3 entered loaded" src="{{$galleryConfig.Icon}}" loading="lazy"/>{{end}}
            </div>
            <p class="text-base leading-relaxed text-gray-500 dark:text-gray-400">{{ $galleryConfig.Description }}</p>
            <hr>
            <p class="text-sm font-semibold text-gray-900 dark:text-white">Links</p>
            <ul>
              {{range $galleryConfig.URLs}}
              <li><a href="{{ . }}" target="_blank">{{ . }}</a></li>
              {{end}}
            </ul>
          </div>

          <!-- Footer -->
          <div class="flex items-center p-4 md:p-5 border-t border-gray-200 rounded-b dark:border-gray-600">
            <button data-modal-hide="model-info-modal" class="py-2.5 px-5 ms-3 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700">
              Close
            </button>
          </div>
        </div>
      </div>
    </div>
    {{ end }}
    {{ end }}

    <!-- Alpine store initialization -->
    <script>
      document.addEventListener("alpine:init", () => {
        Alpine.store("chat", {
          history: [],
          languages: [undefined],
          systemPrompt: "",
          mcpMode: false,
          clear() {
            this.history.length = 0;
          },
          add(role, content, image, audio) {
            const N = this.history.length - 1;
            if (this.history.length && this.history[N].role === role) {
              this.history[N].content += content;
              this.history[N].html = DOMPurify.sanitize(
                marked.parse(this.history[N].content)
              );
            } else {
              let c = "";
              const lines = content.split("\n");
              lines.forEach((line) => {
                c += DOMPurify.sanitize(marked.parse(line));
              });
              this.history.push({ role, content, html: c, image, audio });
            }
            document.getElementById('messages').scrollIntoView(false);
            const parser = new DOMParser();
            const html = parser.parseFromString(
              this.history[this.history.length - 1].html,
              "text/html"
            );
            const code = html.querySelectorAll("pre code");
            if (!code.length) return;
            code.forEach((el) => {
              const language = el.className.split("language-")[1];
              if (this.languages.includes(language)) return;
              const script = document.createElement("script");
              script.src = `https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.8.0/build/languages/${language}.min.js`;
              document.head.appendChild(script);
              this.languages.push(language);
            });
          },
          messages() {
            return this.history.map((message) => ({
              role: message.role,
              content: message.content,
              image: message.image,
              audio: message.audio,
            }));
          },
        });

        window.copyToClipboard = (content) => {
          const tempElement = document.createElement('div');
          tempElement.innerHTML = content;
          const text = tempElement.textContent || tempElement.innerText;

          navigator.clipboard.writeText(text).then(() => {
            alert('Copied to clipboard!');
          }).catch(err => {
            console.error('Failed to copy: ', err);
          });
        };
      });
    </script>
  </body>
</html>
